#pragma once

#include "GetEphemInterface.h"
#include "Excptn.h"


class CDeEphemeride
{
	typedef eBodies eBody;
	//typedef RetValue double;

	class CBuffer
	{
		enum {eBuffAllocCount = 10};
		ifstream	&	m_inFile;
		vector<double>  m_data;
		int				m_nBlockSize;
		DWORD			m_dwFileSize;
		struct Sbuf
		{
			Sbuf(): dwFrom(0), dwTo(0), pData(NULL), nOrder(0) {}
			DWORD		dwFrom;
			DWORD		dwTo;
			double *	pData;
			int			nOrder;
		} m_bufs[2];
		
	public:
		CBuffer(ifstream & inFile);
		void SetCoeffCount(int ncount);
		const double * GetData(DWORD dwOffset);
	};

	class CPolynomialCoefficients
	{
		vector<double>	m_vecData;
		double			m_dPrevTime;
	public:
		CPolynomialCoefficients();
		const double * GetPolinom(int nSize, double dTime);
	};

	
public:
	class CError:			protected CExcptn {}; 
	class CNoFile:			public CError { public: CNoFile(LPCTSTR stzName) {	m_ss << _T("Can not open file: ") << stzName;} 	};
	class CUnknownBoby:		public CError { public: CUnknownBoby(int n)		{m_ss << _T("Body with unknown id:") << n << _T(" was request"); }	};
	class COutOfTimeRange:	public CError {public: COutOfTimeRange(double dJD) {m_ss << _T("requested time ouf of valid ephemeride time range"); }};

public:
	CDeEphemeride (LPCTSTR stzEphemFileName);
	virtual ~CDeEphemeride (void);

	bool GetCoord(eBody body, double dJD, double dOut[6]);
	bool GetCoord1(double dJD, double dOut[12][6]);

private:
	void ProcessCoef();
	void GetPosition(
		double dChebyshevTime,      /* Value of x over [-1, 1] for Chebyshev interpolation */
		double dSubIntervalDay,		/* Span in time of subinterval, for velocity */
		const double *dChebyshevCoef,		/* Chebyshev coefficients */
		int nCoordCounts,			/* Total number of coordinates to interpolate */
		int nCoefPerCoord,			/* Number of Chebyshev coefficients per coordinate */
		double *pv);				/* Array to hold position in 1st half, velocity in 2nd */
	

private:
	struct ephcom_Header {
		struct TimeRange_t 
		{
			double dBegin;
			double dEnd;
			double dStep;
		};
		struct IndexPointers_t       
		{
			int nStartingPoint;
			int nCoefPerCoord;
			int nSubBlockPerBlock;
		};

		char ttl[3][86];   /* Hold up to 14*6=84 characters + "\n\0" */
		char cnam[400][8]; /* Hold up to 400 6-character names ending with '\0' */
		TimeRange_t TimeRange;   /* start epoch, stop epoch, step size */
		int nval;          /* number of values for cval, to compare with ncon */
		int ncon;          /* Number of assigned in cnam */
		double au;         /* km/astronomical unit */
		double emrat;      /* Earth-Moon mass ratio */
		IndexPointers_t IndexPointers [12];  /* index pointers into Chebyshev coefficients */
		int numde;         /* ephemeris number */
		IndexPointers_t Libration;        /* libration pointer in a block */
		double clight;     /* Speed of light, km/sec */
		int ksize;         /* block size, in first line of ASCII header */
		int ncoeff;        /* number of Chebyshev coefficients in data blocks */
		double cval[400];  /* constant values, corresponding to cnam names */
		int numle;         /* lunar ephemeris number (can be same # as numde) */
		int maxcheby;      /* maximum Chebyshev coefficients for a body */
	};

	ephcom_Header	m_header;
	ifstream		m_inFile; 

	CBuffer			m_buffer;
	CPolynomialCoefficients	m_coeff;
};

